home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-9.10-netbook-remix-PL.iso / casper / filesystem.squashfs / usr / share / pyshared / nevow / livetest.py < prev    next >
Text File  |  2006-04-14  |  14KB  |  366 lines

  1.  
  2. from twisted.internet import defer
  3. from nevow import livepage, loaders, tags, rend, static, entities, util
  4. from nevow.livepage import js
  5.  
  6.  
  7. testFrameNode = js.testFrameNode
  8. contentDocument = testFrameNode.contentDocument
  9. gid = contentDocument.getElementById
  10. XPathResult = js.XPathResult
  11. null = js.null
  12.  
  13.  
  14. class xpath(object):
  15.     def __init__(self, path):
  16.         self.path = path
  17.  
  18.     def __repr__(self):
  19.         return 'nevow.livetest.xpath(%r)' % (self.path, )
  20.  
  21.     def _asjs(self, localName):
  22.         yield livepage.var(
  23.             js.targetXPathResult,
  24.             contentDocument.evaluate(self.path,
  25.                                      contentDocument,
  26.                                      null,
  27.                                      XPathResult.ANY_TYPE,
  28.                                      null)), livepage.eol
  29.         yield livepage.var(
  30.             localName,
  31.             js.targetXPathResult.iterateNext()), livepage.eol
  32.  
  33.  
  34. class Driver(object):
  35.     def __init__(self, handle, suite):
  36.         self.handle = handle
  37.         self.suite = list(suite)
  38.         self.results = {}
  39.         self.state = 0
  40.         self.iterator = self.drive()
  41.         self.nextTest()
  42.  
  43.     passes = 0
  44.     failures = 0
  45.  
  46.     def drive(self):
  47.         for i, test in enumerate(self.suite):
  48.             self.state = i
  49.             action, target, parameter = test
  50.             actionCallable = getattr(self, 'action_%s' % (action, ), None)
  51.             if actionCallable is not None:
  52.                 test = actionCallable(target, parameter)
  53.                 if test is not None:
  54.                     yield  test
  55.  
  56.         self.handle.send(livepage.set('test-status', 'Complete'))
  57.  
  58.     def nextTest(self):
  59.         try:
  60.             test = self.iterator.next()
  61.         except StopIteration:
  62.             return
  63.         self.handle.send(test)
  64.  
  65.     def passed(self):
  66.         self.results[self.state] = True
  67.         self.passes += 1
  68.         self.handle.send(js.passed(self.state))
  69.         self.nextTest()
  70.  
  71.     def failed(self, text=''):
  72.         self.results[self.state] = False
  73.         self.failures += 1
  74.         self.handle.send(js.failed(self.state, text))
  75.         self.nextTest()
  76.  
  77.     def checkException(self):
  78.         def continueTests(ctx, status):
  79.             if status == 'passed':
  80.                 self.passed()
  81.             else:
  82.                 self.failed()
  83.  
  84.         continuer = self.handle.transient(continueTests)
  85.         return livepage.anonymous(
  86.             [livepage.js("if (testFrameNode.contentDocument.title != 'Exception') {\n\t"),
  87.             continuer('passed'),
  88.             livepage.js("\n} else {\n\t"),
  89.             continuer('failed'),
  90.             livepage.js("\n}")])
  91.  
  92.     def action_visit(self, target, param):
  93.         yield js.addLoadObserver(self.checkException()), livepage.eol
  94.         yield js.setContentLocation(target), livepage.eol
  95.  
  96.     def action_assert(self, target, param):
  97.         def doAssert(ctx, actual):
  98.             if param == actual:
  99.                 self.passed()
  100.             else:
  101.                 self.failed("%r != %r" % (param, actual))
  102.  
  103.         if isinstance(target, xpath):
  104.             yield target._asjs(js.targetNode)
  105.         else:
  106.             yield livepage.var(js.targetNode, gid(target)), livepage.eol
  107.  
  108.         yield self.handle.transient(
  109.             doAssert, js.targetNode.innerHTML)
  110.  
  111.     def action_value(self, target, param):
  112.         def doAssert(ctx, actual):
  113.             if param == actual:
  114.                 self.passed()
  115.             else:
  116.                 self.failed()
  117.         if isinstance(target, xpath):
  118.             yield target._asjs(js.targetNode)
  119.         else:
  120.             yield livepage.var(js.targetNode, gid(target)), livepage.eol
  121.         yield self.handle.transient(
  122.             doAssert, js.targetNode.value)
  123.  
  124.     def action_follow(self, target, param):
  125.         if isinstance(target, xpath):
  126.             yield target._asjs(js.targetNode)
  127.         else:
  128.             yield livepage.var(js.targetNode, gid(target)), livepage.eol
  129.  
  130.         yield [
  131.             js.addLoadObserver(self.checkException()),
  132.             livepage.eol,
  133.             js.setContentLocation(js.targetNode.href)]
  134.  
  135.     def action_post(self, target, param):
  136.         def passed(ctx):
  137.             self.passed()
  138.  
  139.         if isinstance(target, xpath):
  140.             yield target._asjs(js.targetForm)
  141.         else:
  142.             yield livepage.var(js.targetForm, contentDocument[target]), livepage.eol
  143.  
  144.         yield livepage.var(js.postTarget, js.targetForm.action), livepage.eol
  145.         for key, value in param.items():
  146.             yield livepage.assign(js.targetForm[key].value, value), livepage.eol
  147.         yield js.addLoadObserver(
  148.             livepage.anonymous(
  149.                 self.handle.transient(passed))), livepage.eol
  150.         yield js.sendSubmitEvent(js.targetForm, livepage.anonymous(js))
  151.  
  152.     def action_submit(self, target, param):
  153.         """This should only be used with livepage, to simulate an onsubmit.
  154.  
  155.         It could be possible to make this work when not testing a livepage
  156.         app, using a monstrosity similar to that used by action_click, below.
  157.         """
  158.         def passed(ctx):
  159.             self.passed()
  160.  
  161.         if isinstance(target, xpath):
  162.             yield target._asjs(js.targetForm)
  163.         else:
  164.             yield livepage.var(js.targetForm, contentDocument[target]), livepage.eol
  165.  
  166.         yield livepage.var(js.postTarget, js.targetForm.action), livepage.eol
  167.         for key, value in param.items():
  168.             yield livepage.assign(js.targetForm[key].value, value), livepage.eol
  169.         yield livepage.var(
  170.             js.inputListener,
  171.             contentDocument.defaultView.listenForInputEvents(
  172.                 livepage.anonymous(
  173.                     self.handle.transient(passed)))), livepage.eol
  174.  
  175.         yield js.sendSubmitEvent(
  176.             js.targetForm,
  177.             livepage.anonymous(
  178.                 contentDocument.defaultView.stopListening(js.inputListener)))
  179.  
  180.     def action_click(self, target, param):
  181.         """TODO: Either decide that this should only be used in the presence
  182.         of a real, honest-to-god livepage app, or figure out some way to simplify
  183.         this monstrosity.
  184.         """
  185.         def passed(ctx):
  186.             self.passed()
  187.  
  188.         if isinstance(target, xpath):
  189.             yield target._asjs(js.targetNode)
  190.         else:
  191.             yield livepage.var(js.targetNode, gid(target)), livepage.eol
  192.  
  193.         ## If the testee is using livepage, we don't want the test to pass
  194.         ## until all input events (and the response javascript from these
  195.         ## input events) have passed. To do this we use listenForInputEvents,
  196.         ## passing a continuation function which will be called when all input
  197.         ## event responses have been evaluated. We call stopListening
  198.         ## immediately after sending the click event. This means we
  199.         ## start listening for input events, simulate the click, then stop listening.
  200.         ## If any input events were initiated during the click, our test only passes
  201.         ## when all event responses have been processed.
  202.  
  203.         ## If we are not using livepage, listenForInputEvents will not be defined.
  204.         ## Because it is hard to do javascript tests (if statement) from python,
  205.         ## ifTesteeUsingLivePage has been defined in livetest-postscripts.
  206.         testDidPass = self.handle.transient(passed)
  207.         yield [
  208.             js.ifTesteeUsingLivePage(
  209.                 ## Using livepage
  210.                 livepage.anonymous(
  211.                     livepage.assign(
  212.                         ## Save the listener in a variable so we can stop listening later
  213.                         js.inputListener,
  214.                         contentDocument.defaultView.listenForInputEvents(
  215.                             ## When all observed events complete, continue running tests
  216.                             livepage.anonymous(
  217.                                 testDidPass)))),
  218.                 ## Not using livepage; do nothing here.
  219.                 livepage.anonymous('')), livepage.eol,
  220.             js.sendClickEvent(
  221.                 ## Click our node.
  222.                 js.targetNode,
  223.                 ## Immediately after clicking the node, run this stuff.
  224.                 livepage.anonymous(
  225.                     js.ifTesteeUsingLivePage(
  226.                         ## We're done clicking the node, and we're using livepage.
  227.                         ## Stop listening for input events. This will fire the continuation
  228.                         ## immediately if no input events were observed; otherwise it
  229.                         ## will wait for all responses to be evaluated before firing the
  230.                         ## continuation.
  231.                         livepage.anonymous(contentDocument.defaultView.stopListening(js.inputListener)),
  232.                         ## We're done clicking the node, and we are not using livepage.
  233.                         ## Call testDidPass.
  234.                         livepage.anonymous(testDidPass))))]
  235.  
  236.     def action_call(self, target, param):
  237.         # Import reactor here to avoid installing default at startup
  238.         from twisted.internet import reactor
  239.         def doit():
  240.             target(self.handle, *param).addCallback(
  241.                 lambda result: self.passed()
  242.             ).addErrback(
  243.                 lambda result: self.failed())
  244.         reactor.callLater(0, doit)
  245.         return ''
  246.  
  247.     def action_fail(self, target, param):
  248.         # Import reactor here to avoid installing default at startup
  249.         from twisted.internet import reactor
  250.         def doit():
  251.             target(self.handle, *param).addCallback(
  252.                 lambda result: self.failed()
  253.             ).addErrback(
  254.                 lambda result: self.passed())
  255.         reactor.callLater(0, doit)
  256.         
  257.  
  258.  
  259. class Tester(livepage.LivePage):
  260.     addSlash = True
  261.     child_css = static.File(util.resource_filename('nevow', 'livetest.css'))
  262.     child_scripts = static.File(util.resource_filename('nevow', 'livetest.js'))
  263.     child_postscripts = static.File(util.resource_filename('nevow', 'livetest-postscripts.js'))
  264.     docFactory = loaders.stan(tags.html[
  265.         tags.head[
  266.             tags.script(src="scripts"),
  267.             tags.link(rel="stylesheet", type="text/css", href="css")],
  268.         tags.body[
  269.             tags.table(id="testprogress")[
  270.                 tags.tr[
  271.                     tags.th["Tests"], tags.th["Pass"], tags.th["Fail"]],
  272.                 tags.tr[
  273.                     tags.td(id="test-status")["Running"],
  274.                     tags.td(id="test-passes", _class="test-passes")[entities.nbsp],
  275.                     tags.td(id="test-failures", _class="test-failures")[entities.nbsp]]],
  276.             tags.table(id="testresults", render=tags.directive('sequence'))[
  277.                 tags.tr(pattern="item", render=tags.directive('test'))[
  278.                     tags.td(title=tags.slot('action'))[tags.slot('action')],
  279.                     tags.td(title=tags.slot('target'))[tags.slot('target')],
  280.                     tags.td(title=tags.slot('parameter'))[tags.slot('parameter')]]],
  281.             tags.iframe(id="testframe", src="asdf"),
  282.             tags.script(src="postscripts"),
  283.             livepage.glue]])
  284.  
  285.     def beforeRender(self, ctx):
  286.         self.testId = 0
  287.  
  288.     def render_test(self, ctx, test):
  289.         ctx.tag(id=("test-", self.testId))
  290.         action, target, parameter = test
  291.         ctx.fillSlots('action', action)
  292.         ctx.fillSlots('target', str(target))
  293.         ctx.fillSlots('parameter', str(parameter))
  294.         self.testId += 1
  295.         return ctx.tag
  296.  
  297.     def goingLive(self, ctx, handle):
  298.         Driver(handle, self.original)
  299.  
  300.  
  301. class ChildXPath(rend.Page):
  302.     docFactory = loaders.stan(
  303.         tags.html[
  304.             tags.body[
  305.                 tags.div[
  306.                     tags.span[
  307.                         tags.div(id='target-node-identifier')[
  308.                             'expected content']]]]])
  309.  
  310.  
  311. def thingThatPasses(_):
  312.     return defer.succeed(None)
  313.  
  314.  
  315. def thingThatFails(_):
  316.     return defer.fail(None)
  317.  
  318.  
  319. class TestTests(rend.Page):
  320.     addSlash = True
  321.     docFactory = loaders.stan(tags.html[tags.a(href="/testtests/tests/")["Run tests"]])
  322.     child_foo = '<html><body><div id="body">foo</div><form method="POST", name="theForm" action="postTarget"><input name="blah" /></form></body></html>'
  323.     child_bar = "bar"
  324.     child_baz = '<html><body onclick="alert(event.clientX);alert( event.clientY);"><div id="body">toot</div><a id="nextPage" href="foo" onclick="alert(\'clicked\')">Foo</a></body></html>'
  325.  
  326.     child_clickHandler = """<html>
  327.     <body>
  328.         <a id="theClicker" onclick="this.innerHTML='Clicked'">Click me!</a>
  329.     </body>
  330. </html>"""
  331.  
  332.     def child_postTarget(self, ctx):
  333.         return rend.Page(
  334.             docFactory=loaders.stan(
  335.                 tags.html[tags.body(id="body")[str(ctx.arg('blah'))]]))
  336.  
  337.     def child_testtests(self, ctx):
  338.         return self
  339.  
  340.     def child_xpath(self, ctx):
  341.         ## print 'lkfjasldkjasd!!!!!!!!'
  342.         return ChildXPath()
  343.  
  344.     child_tests = Tester([
  345.     ('visit', '/testtests/xpath', ''),
  346.     ('assert', xpath('/html/body/div/span/div[@id="target-node-identifier"]'), 'expected content'),
  347.     ('visit', '/testtests/foo', ''),
  348.     ('visit', '/testtests/bar', ''),
  349.     ('visit', '/testtests/baz', ''),
  350.     ('assert', 'body', 'toot'),
  351.     ('follow', 'nextPage', ''),
  352.     ('assert', 'body', 'foo'),
  353.     ('post', 'theForm', dict(blah="blah")),
  354.     ('assert', 'body', 'blah'),
  355.     ('visit', '/testtests/clickHandler', ''),
  356.     ('click', 'theClicker', ''),
  357.     ('assert', 'theClicker', 'Clicked'),
  358.     ('call', thingThatPasses, ()),
  359.     ('fail', thingThatFails, ())
  360. ])
  361.  
  362.  
  363. def createResource():
  364.     return TestTests()
  365.  
  366.